/*
 * Copyright (c) 2009, Luke Emrose
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.  Neither the name of Luke Emrose Sole Trader nor the
 * names of its contributors may be used to endorse or promote
 * products derived from this software without specific prior written
 * permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 #ifndef __TIMESTATS_H__
#define __TIMESTATS_H__

// boost includes
#include <boost/timer.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/lexical_cast.hpp>

// std includes
#include <string>

/**
 * @brief
 * Exceptionally useful timer implementation putting together the best
 * bits of boost timing for portable CPU, IO, and WALL clock timing,
 * To the maximum precision of timing on the machine performing the timing
 */
class timestats
{
	public:
		/**
		 * @brief
		 * constructor - restarts the timers
		 */
		timestats()
		{
			// initialize the timers
			_cpu_timer = boost::timer();
			_wall_timer = boost::posix_time::microsec_clock::local_time();
		}

		/**
		 * @brief
		 * reset - restarts the timers
		 */
		void restart( void )
		{
			// re-initialize the timers
			_cpu_timer = boost::timer();
			_wall_timer = boost::posix_time::microsec_clock::local_time();
		}

		/**
		 * @brief
		 * returns the elapsed times pre-formatted as a std::string
		 */
		std::string elapsed( void ) const
		{
			std::string result;
			result = "CPU Time = ";
			result += boost::lexical_cast< std::string >( _cpu_timer.elapsed() );
			result += " seconds";
			result += ", Wall Time = ";
			result += boost::posix_time::to_simple_string( boost::posix_time::microsec_clock::local_time() - _wall_timer );
			return result;
		}

		/**
		 * @brief
		 * destructor
		 */
		~timestats() { }

	private:
		boost::timer _cpu_timer;
		boost::posix_time::ptime _wall_timer;
};

#endif